<template>
  <div>
    <Upload
      v-model:file-list="fileList"
      :show-upload-list="false"
      :customRequest="customRequest"
      :beforeUpload="beforeUpload"
    >
      <a-button type="text" v-show="showUploadButton">
        <Space><SvgIcon name="upload" />上传</Space>
      </a-button>
    </Upload>
    <Space v-show="!showUploadButton">
      <SvgIcon :name="previewIcon" />
      <span>{{ uploadFile?.name }}</span>
      <Tooltip>
        <template #title>
          <span>{{ DELETE }}</span>
        </template>
        <a-button @click="removeFile" type="text">
          <SvgIcon name="delete" style="color: red" />
        </a-button>
      </Tooltip>
    </Space>
    <Progress
      v-show="!showUploadButton && getAutoUpload"
      type="circle"
      :width="20"
      :percent="percent"
      :status="status"
    />
  </div>
</template>

<script lang="ts" setup>
  import { computed, ref, unref, watch } from 'vue';
  import { Progress, Space, Tooltip, Upload, UploadFile } from 'ant-design-vue';
  import SvgIcon from '/@/components/Icon/src/SvgIcon.vue';
  import { useI18n } from '/@/hooks/web/useI18n';
  import { useMessage } from '/@/hooks/web/useMessage';

  import { DELETE } from '/@/constant';
  import { FileType, parseFileType } from '/@/utils/file/fileUtils';
  import { UploadFile as UF } from './typing';

  const props = defineProps({
    value: {
      type: Object,
    },
    maxSize: {
      type: Number,
      default: (): number => 5,
    },
    api: {
      type: Function,
      required: true,
    },
    autoUpload: {
      type: Boolean,
      default: (): boolean => true,
    },
  });
  const emit = defineEmits(['update:value', 'change']);

  const { createMessage } = useMessage();
  const { t } = useI18n();

  const fileList = ref<UploadFile[]>([]);
  const percent = ref<number>(0);
  const status = ref<string>('active');
  const uploadFile = ref<File | null>(null);

  watch(
    () => props.value,
    (value) => {
      if (!value) {
        fileList.value = [];
      }
    },
  );

  const showUploadButton = computed(() => {
    return unref(fileList).length === 0;
  });

  const getAutoUpload = computed(() => {
    const { autoUpload } = props;
    return autoUpload;
  });

  const beforeUpload = (file) => {
    uploadFile.value = file;
    const autoUpload = unref(getAutoUpload);
    if (!autoUpload) {
      if (!checkFile(file)) {
        updateValue(null);
        fileList.value = [];
        return false;
      }
      updateValue({ file, upload: handleUpload });
    }
    return autoUpload;
  };

  const updateValue = (uf: UF | null) => {
    emit('update:value', uf);
    emit('change', uf);
  };

  const previewIcon = computed(() => {
    if (!showUploadButton.value) {
      const { name } = unref(uploadFile) as File;
      const fileType = parseFileType({ name });

      let result;
      switch (fileType) {
        case FileType.EXCEL:
          result = 'excel';
          break;
        case FileType.WORD:
          result = 'word';
          break;
        case FileType.PDF:
          result = 'pdf';
          break;
        case FileType.TXT:
          result = 'txt';
          break;
        case FileType.IMAGE:
          result = 'image';
          break;
        case FileType.PPT:
          result = 'ppt';
          break;
        default:
          result = 'file';
          break;
      }
      return result;
    }
    return '';
  });

  const removeFile = () => {
    fileList.value = [];
    percent.value = 0;
    status.value = 'active';
  };

  const checkFile = (file) => {
    const { maxSize } = props;
    // 设置最大值，则判断
    if (maxSize && file.size / 1024 / 1024 >= maxSize) {
      createMessage.error(t('component.upload.maxSizeMultiple', [maxSize]));
      removeFile();
      return false;
    }
    return true;
  };

  const customRequest = async ({ file }) => {
    if (!checkFile(file)) {
      return false;
    }
    function onUploadProgress(progressEvent: ProgressEvent) {
      percent.value = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
    }
    const res = await handleUpload(onUploadProgress);
    if (res) {
      const { data } = res;
      updateValue({
        file,
        upload: () => {
          console.warn('数据已经自动上传，请勿重复上传');
        },
        ...data,
      } as UF);
    }
  };

  const handleUpload = async (onUploadProgress): Promise<any> => {
    const file = unref(uploadFile) as File;
    const { name } = file;
    const { api } = props;
    try {
      const res = await api({ file, data: { type: parseFileType({ name }) } }, onUploadProgress);
      status.value = 'success';
      const { data } = res;
      updateValue({ file, ...data } as UF);
      return res;
    } catch (e) {
      status.value = 'exception';
      return null;
    }
  };
</script>

<style scoped></style>
